#pragma once

#include <entt/entt.hpp>
#include "qlib/all.h"

namespace qbe::auxiliary {

//获取cell中所有基本图形
std::vector<entt::entity> getCellAllGraph(qlib::Cell::s_ptr cell);
//向cell中加入基本图形
std::vector<entt::entity> AddGraphToCell(qlib::Cell::s_ptr cell, std::vector<std::any> grpahs);
std::vector<std::any> getGraph(qlib::Cell::s_ptr cell, std::vector<entt::entity> entities);

std::vector<std::shared_ptr<qlib::Cell>> deepCopyAllRefs(std::vector<std::shared_ptr<qlib::Reference>> refs);

std::vector<std::any> copyElement(qlib::Cell::s_ptr current_cell, std::vector<entt::entity>& selected_eles);
std::vector<qlib::Vec2d> calBonndingBox(std::vector<std::any> selected);
void translateGraph(std::vector<std::any> graphs, qlib::Vec2d offset);
std::string duplicateNameVerify(std::string name, std::vector<std::string> name_list);

bool pointIsSegmentInternal(qlib::Vec2d& point, qlib::Vec2d& segment_1, qlib::Vec2d& segment_2, double scale);
double distance(const qlib::Vec2d& a, const qlib::Vec2d& b);
bool findPointsOnLine(const qlib::Vec2d& A, const qlib::Vec2d& B, const qlib::Vec2d& C, qlib::Vec2d& Q1, qlib::Vec2d& Q2, double scale);
std::vector<qlib::Vec2<double>> calArrayPosition(double start_x, double start_y, int row, int col, qlib::Vec2<double> row_vector,
                                                 qlib::Vec2<double> col_vector);
std::shared_ptr<double> getSlope(qlib::Vec2d p1, qlib::Vec2d p2);
// 直线斜率和y交点 直线表达式 y= slope * x + intercept
std::vector<std::shared_ptr<double>> slopeAndIntercept(qlib::Vec2d p1, qlib::Vec2d p2, std::shared_ptr<double> s);
bool lineIntersectSeg(qlib::Vec2d p, qlib::Vec2d q, qlib::Vec2d A, qlib::Vec2d B, qlib::Vec2d& inter_point);
qlib::Vec2d GetFootOfPerpendicular(const qlib::Vec2d& pt, const qlib::Vec2d& begin, const qlib::Vec2d& end);
qlib::Vec2d calculateIntersectionPoint(std::vector<std::shared_ptr<double>> line_a, std::vector<std::shared_ptr<double>> line_b);
std::vector<int> getAroundIndex(int index, int total, int length, int space);

class BoundingBox {
 public:
  BoundingBox() {}
  ~BoundingBox() {}
  void addPoints(std::vector<qlib::Vec2d>& points) {
    for (auto i : points) {
      if (min.x > i.x)
        min.x = i.x;
      if (min.y > i.y)
        min.y = i.y;

      if (max.x < i.x)
        max.x = i.x;
      if (max.y < i.y)
        max.y = i.y;
    }
  }
  qlib::Vec2d min = qlib::Vec2d(10e7, 10e7);
  qlib::Vec2d max = qlib::Vec2d(-10e7, -10e7);
};

double angle_direction(qlib::Vec2d p1, qlib::Vec2d p2);
std::vector<qlib::Vec2d> pointExtendToLine(qlib::Vec2d pos, double direct, double length);
uint32_t UpdateCellInstanceNameMaxId(std::shared_ptr<qlib::Cell> cell);
std::vector<qlib::Vec2d> connectLine(std::vector<std::shared_ptr<qlib::Path>>& lines);
void UpdateCellMaxPinId(std::shared_ptr<qlib::Cell> cell);
}  // namespace qbe::auxiliary